package metamodel;

import metamodel.parser.ClassResolver;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * User: felix
 * Date: 30.05.2005
 * Time: 21:26:01
 */
public class ClassNode {
    String  typeName;
    List<Property>   properties;
    ClassNode declaringParent;
    String label;
    private ClassResolver resolver;

    public String toString() {
        return "record "+getTypeName();
    }

    public ClassNode getDeclaringParent() {
        return declaringParent;
    }

    public void setDeclaringParent(ClassNode declaringParent) {
        this.declaringParent = declaringParent;
    }

    //todo: delete this constructor...
    public ClassNode(String type) {

        this.typeName = type;

    }


    public void setResolver(ClassResolver resolver) {
        this.resolver = resolver;
    }

    public ClassNode(String type, List<Property> properties) {
        this.typeName = type;
        this.properties=properties;
        for (Iterator iterator = properties.iterator(); iterator.hasNext();) {
            Property property = (Property) iterator.next();
            property.setEnclosing(this);
        }
     }

    public ClassNode() {
    }

    public List<Property> getProperties() {
         if (properties==null)
             properties=new ArrayList<Property>(4);
        return properties;
    }

    public String getTypeName() {
        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName;
    }

    public void setProperties(List properties) {
        this.properties = properties;
    }

    public Class getType(){
            String typeName = getTypeName();
            return resolveClass(typeName);
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public String getLabel() {
        return label;
    }

    /** lateron we will integrate our package name resolution here*/
    protected Class resolveClass(String typeName) {
        try {
            return getClass().getClassLoader().loadClass(typeName);
        } catch (ClassNotFoundException e) {
        }
        return getResolver().resolveClass(typeName);
    }

    protected ClassResolver getResolver() {
        if (this.resolver!=null){
            return resolver;
        }
        else return declaringParent.getResolver();
    }

    /** @param value pseudo parameter needed only in the subclass implementation
     * todo: this is not a nice solution */
    public Object createInstance(Object value) {
        try {
            if (value!=null){
            if (getType().isAssignableFrom(value.getClass())){
                Object clone=null;
                clone=value.getClass().newInstance();
                return clone;

            }else{
                throw new RuntimeException("Class cast problem");
            }
            }else{
                return getType().newInstance();
            }

        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

     public boolean isPoly(){
         return false;
     }

    public Property getProperty(String name) {
        for (Iterator iterator = properties.iterator(); iterator.hasNext();) {
            Property p= (Property) iterator.next();
            if (p.getName().equals(name)) {
                return p;
            }
        }
        throw new RuntimeException("No Property of name "+name+" found in type "+getTypeName());
    }

    public PolyClassNode getPoly() {
        throw new RuntimeException("Class cast exception I'm not a PolyClassNode");
    }
}
